package com.iring.service.common.impl;

import javax.transaction.Transactional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import com.iring.domain.config.prop.LocalConfigProperties;
import com.iring.domain.config.prop.VOSCustomerProperties;
import com.iring.domain.config.prop.VOSPhoneProperties;
import com.iring.dao.common.ConsumptionDao;
import com.iring.dao.common.UserDao;
import com.iring.dao.vos.CommonVosDao;
import com.iring.dao.vos.SuiteOrderDao;
import com.iring.domain.common.User;
import com.iring.domain.vos.suite.CreateSuiteOrder;
import com.iring.domain.vos.suite.InfoSuite;
import com.iring.domain.vos.suite.SuiteOrder;
import com.iring.exception.ParamInvalidException;
import com.iring.exception.config.ErrorEnum;
import com.iring.service.common.AllSuiteService;
import com.iring.service.common.SuiteService;
import com.iring.util.common.DateUtil;
import com.iring.vo.vos.AddSuiteVO;
import com.iring.vo.vos.DeleteSuiteVO;

/**
 * @author wanggan
 */
@Service
public class SuiteServiceImpl implements SuiteService {

    @Autowired
    UserDao userDao;

    @Autowired
    ConsumptionDao consumptionDao;

    @Autowired
    LocalConfigProperties localUserProperties;

    @Autowired
    VOSCustomerProperties vosCustomerProperties;

    @Autowired
    VOSPhoneProperties vosPhoneProperties;

    @Autowired
    CommonVosDao commonVosDao;

    @Autowired
    SuiteOrderDao suiteOrderDao;

    @Autowired
    AllSuiteService allSuiteService;

    private static final Logger logger = LoggerFactory.getLogger(SuiteServiceImpl.class);

    @Transactional
    @Override
    public Boolean deleteOrderPackage(DeleteSuiteVO deleteSuiteVO, String username) {
        Integer orderId = deleteSuiteVO.getOrderid();
        if(null == orderId){
            throw new ParamInvalidException("orderid is null");
        }
        Boolean isDelete = commonVosDao.deleteOrderSuite(orderId);
        if (isDelete) {
            logger.info("username={},Unsubscribe suite success suiteOrderId={}", username,deleteSuiteVO.getOrderid());
            return Boolean.TRUE;
        }
        throw new ParamInvalidException(ErrorEnum.DELETE_PACKAGE_FAILED);
    }

    @Override
    public String listAllOrderSuite(String username) {
        SuiteOrder suiteOrder = new SuiteOrder(username, vosCustomerProperties.getOwnerType());
        return suiteOrderDao.GetPhoneOrderSuite(suiteOrder);
    }

    @Override
    public String listAllPhoneSuite(String username) {
        SuiteOrder suiteOrder = new SuiteOrder(username, vosCustomerProperties.getOwnerType());
        return suiteOrderDao.GetPhoneSuite(suiteOrder);
    }

    @Transactional
    @Override
    public synchronized User createSuite(AddSuiteVO addSuiteVO, String username) {
        Integer suiteId = addSuiteVO.getSuiteid();
        if(null == suiteId){
            throw new ParamInvalidException("suiteid is null");
        }
        // 获取当前套餐id的信息
        Integer suiteid = addSuiteVO.getSuiteid();
        Object object = getInfoSuite(suiteid);
        if (!(object instanceof InfoSuite)) {
            throw new ParamInvalidException(ErrorEnum.GET_PACKAGE_INFO_FAILED);
        } else {
            InfoSuite infoSuite = (InfoSuite) object;
            Assert.notNull(infoSuite, "suite info must not be null");
            Double rentFee = infoSuite.getRentFee();
            User user = userDao.findByUsername(username);

            if (user.getRestAmounts().compareTo(rentFee) < 0) {// 如果剩余金额小于套餐余额
                throw new ParamInvalidException(ErrorEnum.AMOUNT_NOT_ENOUGH);
            } else {
                CreateSuiteOrder order = createSuiteOrder(username, suiteid);
                if (!buyVosSuite(order)) {// 如果购买套餐失败
                    throw new ParamInvalidException(ErrorEnum.BUY_PACKAGE_FAILED);
                } else {
                    // 如果购买成功
                    Double result = consumptionDao.insertConsumptionInfoProc(username,
                            localUserProperties.getPackageOpt(), rentFee);
                    if (result.compareTo(0.0) == 1) {
                        user.setRestAmounts(result);
                        return user;
                    }
                    logger.info("create local suite fail");
                    throw new ParamInvalidException(ErrorEnum.BUY_PACKAGE_FAILED);
                }
            }
        }
    }

    /**
     * 向vos发起购买套餐请求
     *
     * @param suiteOrder
     *            {@link CreateSuiteOrder}
     * @return 购买结果
     */
    private Boolean buyVosSuite(CreateSuiteOrder suiteOrder) {
        Boolean ispay = commonVosDao.createVosSuiteOrder(suiteOrder);
        if (ispay) {
            return Boolean.TRUE;
        } else {
            Boolean isokay = false;
            for (int i = 0; i < 3; i++) {
                ispay = commonVosDao.createVosSuiteOrder(suiteOrder);
                if (ispay) {
                    isokay = true;
                    break;
                }
            }
            // 如果执行结果成功了,则返回true
            if (isokay) {
                return Boolean.TRUE;
            } else {
                return Boolean.FALSE;
            }
        }
    }

    /**
     * 根据suiteid获取租金信息
     *
     * @param suiteid
     *            套餐id
     * @return 套餐信息
     */
    private InfoSuite getInfoSuite(Integer suiteid) {
        // 通过套餐id获取套餐的租金
        Object object = allSuiteService.getSingleSuiteCache(suiteid);
        if (null == object) {
            return null;
        }
        return (InfoSuite) object;
    }

    /**
     * 创建套餐订单
     *
     * @param username
     *            用户名
     * @param suited
     *            套餐id
     * @return {@link CreateSuiteOrder}
     */
    private CreateSuiteOrder createSuiteOrder(String username, Integer suited) {
        // 设置套餐订单
        CreateSuiteOrder order = new CreateSuiteOrder();
        order.setOwnerName(username);
        order.setOwnerType(vosCustomerProperties.getOwnerType());
        order.setSuiteId(suited);
        order.setRentPercent(vosCustomerProperties.getRentPercent());
        order.setAvailableTime(DateUtil.getTimestamp());
        order.setFailedProcessMode(vosPhoneProperties.getFailedProcessMode());
        return order;
    }
}
